home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / tests / processTree / RCS / processTree.c,v < prev   
Encoding:
Text File  |  1992-07-17  |  11.8 KB  |  611 lines

  1. head     1.5;
  2. branch   ;
  3. access   ;
  4. symbols  srv030:1.5 srv027:1.5 srv026:1.5 srv024:1.5 srv021:1.5 srv018:1.5 srv014:1.5 srv010:1.5 srv008:1.5 srv007:1.5 srv006:1.5 srv004:1.5;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.5
  10. date     92.04.29.22.32.45;  author kupfer;  state Exp;
  11. branches ;
  12. next     1.4;
  13.  
  14. 1.4
  15. date     91.11.14.20.28.57;  author kupfer;  state Exp;
  16. branches ;
  17. next     1.3;
  18.  
  19. 1.3
  20. date     91.10.18.18.49.36;  author kupfer;  state Exp;
  21. branches ;
  22. next     1.2;
  23.  
  24. 1.2
  25. date     91.10.04.14.17.12;  author kupfer;  state Exp;
  26. branches ;
  27. next     1.1;
  28.  
  29. 1.1
  30. date     91.10.02.18.25.41;  author kupfer;  state Exp;
  31. branches ;
  32. next     ;
  33.  
  34.  
  35. desc
  36. @Test program to create a tree of processes to test process creation
  37. and termination.
  38. @
  39.  
  40.  
  41. 1.5
  42. log
  43. @Add USE_STDIO ifdef.
  44. @
  45. text
  46. @/* 
  47.  * processTree.c --
  48.  *
  49.  *    Test program to do lots of forks and execs.  Basically the program 
  50.  *    spawns a small tree of processes, in which a process forks off some 
  51.  *    children, waits a random interval, then exits.
  52.  *    
  53.  *    Usage: processTree [ numSecs ]
  54.  *    
  55.  *    where "numSecs" is the minimum number of seconds to run.  (The 
  56.  *    default is to run forever.)  After numSecs seconds the top-level 
  57.  *    process stops creating new processes, and eventually the program 
  58.  *    exits. 
  59.  *
  60.  * Copyright 1991 Regents of the University of California
  61.  * Permission to use, copy, modify, and distribute this
  62.  * software and its documentation for any purpose and without
  63.  * fee is hereby granted, provided that this copyright
  64.  * notice appears in all copies.  The University of California
  65.  * makes no representations about the suitability of this
  66.  * software for any purpose.  It is provided "as is" without
  67.  * express or implied warranty.
  68.  */
  69.  
  70. #ifndef lint
  71. static char rcsid[] = "$Header: /user5/kupfer/spriteserver/tests/processTree/RCS/processTree.c,v 1.4 91/11/14 20:28:57 kupfer Exp Locker: kupfer $ SPRITE (Berkeley)";
  72. #endif /* not lint */
  73.  
  74. #include <errno.h>
  75. #include <sprite.h>
  76. #include <stdio.h>
  77. #include <stdlib.h>
  78. #include <string.h>
  79. #include <sys/wait.h>
  80. #include <sys/time.h>
  81. #include <sys/types.h>
  82. #include <sys/resource.h>
  83. #include <test.h>
  84. #include <unistd.h>
  85.  
  86. #define USE_STDIO        /* use printf instead of Test_PutTime */
  87.  
  88. #define NUM_CHILDREN_1ST    2 /* number of immediate children to keep 
  89.                    * running */
  90. #define MAX_CHILDREN_2ND    10 /* maximum number of children to be 
  91.                     * created by a first-generation child */
  92. #define MAX_PRINTFS        5 /* maximum number of printfs for a 
  93.                    * process to do before exiting */
  94. #define MAX_SLEEP_TIME        20 /* maximum number of seconds to sleep 
  95.                     * between printf's */
  96.  
  97. extern int FromInterval();
  98.  
  99. /* Forward references: */
  100.  
  101. static void BeAChild();
  102. static int Lookup();
  103. static pid_t MakeChild();
  104. static void PrintfLoop();
  105. static void PrintTime();
  106. static void ReapChildren();
  107. static void SleepSome();
  108.  
  109.  
  110. /*
  111.  *----------------------------------------------------------------------
  112.  *
  113.  * main --
  114.  *
  115.  *    Run forever; start a new top-level child when one exits.
  116.  *
  117.  * Results:
  118.  *    None.
  119.  *
  120.  * Side effects:
  121.  *    None.
  122.  *
  123.  *----------------------------------------------------------------------
  124.  */
  125.  
  126. void
  127. main(argc, argv)
  128.     int argc;
  129.     char **argv;
  130. {
  131.     int child;
  132.     pid_t children[NUM_CHILDREN_1ST];
  133.     pid_t deadDescendant;
  134.     time_t stopTime = 0;    /* if non-zero, don't create new processes 
  135.                  * after this time */
  136.  
  137.     /* 
  138.      * Initialization.
  139.      */
  140.     for (child = 0; child < NUM_CHILDREN_1ST; ++child) {
  141.     children[child] = MakeChild(TRUE);
  142.     }
  143.     if (argc > 1) {
  144.     stopTime = time((time_t *)0) + atoi(argv[1]);
  145.     }
  146.  
  147.     /* 
  148.      * When a direct descendant dies, start a replacement, up until the
  149.      * stopping time (if any).  If we're running as the initial process, we
  150.      * inherit 2nd generation processes as well.  When those die, take no
  151.      * additional action.
  152.      */
  153.     
  154.     for (;;) {
  155.     deadDescendant = wait((union wait *)0);
  156.     if (deadDescendant < 0) {
  157.         if (stopTime == 0 || time((time_t *)0) < stopTime) {
  158.         perror("Wait at top level failed");
  159.         exit(1);
  160.         }
  161.         exit(0);
  162.     }
  163.     child = Lookup(deadDescendant, children);
  164.     if (child != -1) {
  165.         if (stopTime == 0 || time((time_t *)0) < stopTime) {
  166.         children[child] = MakeChild(TRUE);
  167.         }
  168.     }
  169.     }
  170. }
  171.  
  172.  
  173. /*
  174.  *----------------------------------------------------------------------
  175.  *
  176.  * MakeChild --
  177.  *
  178.  *    Make a child process.
  179.  *
  180.  * Results:
  181.  *    In the parent, returns the pid of the child.  In the child, never 
  182.  *    returns.
  183.  *
  184.  * Side effects:
  185.  *    None.
  186.  *
  187.  *----------------------------------------------------------------------
  188.  */
  189.  
  190. static pid_t
  191. MakeChild(moreChildren)
  192.     Boolean moreChildren;    /* should the child make addition children? */
  193. {
  194.     pid_t childPid;
  195.  
  196.     childPid = fork();
  197.     switch (childPid) {
  198.     case -1:
  199.     perror("Can't create child");
  200.     exit(1);
  201.     break;
  202.     case 0:
  203.     BeAChild(moreChildren);
  204.     exit(0);
  205.     break;
  206.     }
  207.  
  208.     return childPid;
  209. }
  210.  
  211.  
  212. /*
  213.  *----------------------------------------------------------------------
  214.  *
  215.  * BeAChild --
  216.  *
  217.  *    Create some number of child processes if asked to do so.  Then do a
  218.  *    random number of printfs, sleeping a random time between printfs
  219.  *    and checking for dead children.  Then return.
  220.  *
  221.  * Results:
  222.  *    None.
  223.  *
  224.  * Side effects:
  225.  *    None.
  226.  *
  227.  *----------------------------------------------------------------------
  228.  */
  229.  
  230. static void
  231. BeAChild(makeChildren)
  232.     Boolean makeChildren;
  233. {
  234.     int numChildren;
  235.     int child;
  236.  
  237.     /* 
  238.      * Reinitialize the random number generator, using our pid.  Otherwise, 
  239.      * all the processes run in lock step.
  240.      */
  241.     srandom(getpid());
  242.  
  243.     /* 
  244.      * Even though we're supposed to make children, we don't want any 
  245.      * grandchildren. 
  246.      */
  247.     if (makeChildren) {
  248.     numChildren = FromInterval(1, MAX_CHILDREN_2ND);
  249.     for (child = 0; child < numChildren; ++child) {
  250.         (void)MakeChild(FALSE);
  251.     }
  252.     }
  253.  
  254.     PrintfLoop(makeChildren);
  255. }
  256.  
  257.  
  258. /*
  259.  *----------------------------------------------------------------------
  260.  *
  261.  * PrintfLoop --
  262.  *
  263.  *    Do a random number of printfs over a random time interval.  Each 
  264.  *    time through the loop, reap any children that have died.
  265.  *
  266.  * Results:
  267.  *    None.
  268.  *
  269.  * Side effects:
  270.  *    None.
  271.  *
  272.  *----------------------------------------------------------------------
  273.  */
  274.  
  275. static void
  276. PrintfLoop(expectChildren)
  277.     Boolean expectChildren;    /* should there be children to reap? */
  278. {
  279.     int numMessages = FromInterval(1, MAX_PRINTFS);
  280.     int msg;            /* message (printf) number */
  281.  
  282.     for (msg = 0; msg < numMessages; ++msg) {
  283.     PrintTime();
  284.     SleepSome();
  285.     if (expectChildren) {
  286.         ReapChildren();
  287.     }
  288.     }
  289. }
  290.  
  291.  
  292. /*
  293.  *----------------------------------------------------------------------
  294.  *
  295.  * PrintTime --
  296.  *
  297.  *    Backspace over the previous time message and write the current 
  298.  *    time.
  299.  *
  300.  * Results:
  301.  *    None.
  302.  *
  303.  * Side effects:
  304.  *    None.
  305.  *
  306.  *----------------------------------------------------------------------
  307.  */
  308.  
  309. static void
  310. PrintTime()
  311. {
  312.     time_t now;
  313. #ifdef USE_STDIO
  314.     char buf[26];
  315. #endif
  316.  
  317.     now = time((time_t *)0);
  318. #ifdef USE_STDIO
  319.     strcpy(buf, ctime(&now));
  320.     buf[24] = '\0';
  321.     printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%s",
  322.        buf);
  323.     fflush(stdout);
  324. #else
  325.     Test_PutTime(now, TRUE);
  326. #endif
  327. }
  328.  
  329.  
  330. /*
  331.  *----------------------------------------------------------------------
  332.  *
  333.  * SleepSome --
  334.  *
  335.  *    Pick a random number of seconds and sleep for that long.
  336.  *
  337.  * Results:
  338.  *    None.
  339.  *
  340.  * Side effects:
  341.  *    None.
  342.  *
  343.  *----------------------------------------------------------------------
  344.  */
  345.  
  346. static void
  347. SleepSome()
  348. {
  349.     int numSecs;
  350.  
  351.     numSecs = FromInterval(1, MAX_SLEEP_TIME);
  352.     sleep(numSecs);
  353. }
  354.  
  355.  
  356. /*
  357.  *----------------------------------------------------------------------
  358.  *
  359.  * ReapChildren --
  360.  *
  361.  *    Reap any dead children.  If there aren't any currently, return.
  362.  *
  363.  * Results:
  364.  *    None.
  365.  *
  366.  * Side effects:
  367.  *    None.
  368.  *
  369.  *----------------------------------------------------------------------
  370.  */
  371.  
  372. static void
  373. ReapChildren()
  374. {
  375.     pid_t childPid;
  376.  
  377.     for (;;) {
  378.     childPid = wait3((union wait *)0, WNOHANG, (struct rusage *)0);
  379.     /* no children died */
  380.     if (childPid == 0) {
  381.         break;
  382.     }
  383.     /* all our children died before we did */
  384.     if (childPid < 0 && errno == ECHILD) {
  385.         break;
  386.     }
  387.     if (childPid < 0) {
  388.         perror("Wait for child failed");
  389.         exit(1);
  390.     }
  391.     }
  392. }
  393.  
  394.  
  395. /*
  396.  *----------------------------------------------------------------------
  397.  *
  398.  * Lookup --
  399.  *
  400.  *    Find the given child in the table of children.
  401.  *
  402.  * Results:
  403.  *    Returns the table index for the child, or -1 if the child isn't in 
  404.  *    the table.
  405.  *
  406.  * Side effects:
  407.  *    None.
  408.  *
  409.  *----------------------------------------------------------------------
  410.  */
  411.  
  412. static int
  413. Lookup(child, childTable)
  414.     pid_t child;
  415.     pid_t *childTable;        /* table with NUM_CHILDREN_1ST entries */
  416. {
  417.     int index;
  418.  
  419.     for (index = 0; index < NUM_CHILDREN_1ST; ++index) {
  420.     if (childTable[index] == child) {
  421.         return index;
  422.     }
  423.     }
  424.  
  425.     return -1;
  426. }
  427.  
  428. @
  429.  
  430.  
  431. 1.4
  432. log
  433. @Fix some comments.
  434. @
  435. text
  436. @d26 1
  437. a26 1
  438. static char rcsid[] = "$Header: /r3/kupfer/spriteserver/tests/processTree/RCS/processTree.c,v 1.3 91/10/18 18:49:36 kupfer Exp Locker: kupfer $ SPRITE (Berkeley)";
  439. d41 2
  440. d268 3
  441. d273 7
  442. d281 1
  443. @
  444.  
  445.  
  446. 1.3
  447. log
  448. @Lint.  Take an argument specifying how long to run.
  449. @
  450. text
  451. @d2 1
  452. a2 1
  453.  * forkExec.c --
  454. d7 7
  455. d26 1
  456. a26 1
  457. static char rcsid[] = "$Header: /r3/kupfer/spriteserver/tests/processTree/RCS/processTree.c,v 1.2 91/10/04 14:17:12 kupfer Exp Locker: kupfer $ SPRITE (Berkeley)";
  458. @
  459.  
  460.  
  461. 1.2
  462. log
  463. @Changes to run under early version of Sprite server.  Lint.
  464. @
  465. text
  466. @d19 1
  467. a19 1
  468. static char rcsid[] = "$Header: /r3/kupfer/spriteserver/tests/processTree/RCS/processTree.c,v 1.1 91/10/02 18:25:41 kupfer Exp Locker: kupfer $ SPRITE (Berkeley)";
  469. d73 3
  470. a75 1
  471. main()
  472. d80 2
  473. d89 3
  474. d94 4
  475. a97 3
  476.      * When a direct descendant dies, start a replacement.  If we're 
  477.      * running as the initial process, we inherit 2nd generation processes 
  478.      * as well.  When those die, take no additional action.
  479. d99 1
  480. a99 1
  481.  
  482. d103 5
  483. a107 2
  484.         perror("Wait at top level failed");
  485.         exit(1);
  486. d111 3
  487. a113 1
  488.         children[child] = MakeChild(TRUE);
  489. d260 1
  490. a260 1
  491.     now = time(0);
  492. @
  493.  
  494.  
  495. 1.1
  496. log
  497. @Initial revision
  498. @
  499. text
  500. @d19 1
  501. a19 1
  502. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.5 91/02/09 13:24:44 ouster Exp $ SPRITE (Berkeley)";
  503. d25 1
  504. a26 1
  505. #include <sys/file.h>
  506. d31 2
  507. a33 2
  508. typedef int pid_t;        /* should be in <sys/types.h> */
  509.  
  510. d43 1
  511. a43 1
  512. int lockFile;            /* file descriptor for shared lock file */
  513. a47 1
  514. static void ClearLock();
  515. a52 1
  516. static void SetLock();
  517. a81 6
  518.     lockFile = open("/users/kupfer/tmp/LockFile", O_RDWR|O_CREAT, 0644);
  519.     if (lockFile < 0) {
  520.     perror("Can't open lock file");
  521.     exit(1);
  522.     }
  523.  
  524. d93 1
  525. a93 1
  526.     deadDescendant = wait(0);
  527. d237 1
  528. a237 1
  529.  *    Uses a lock file to ensure that the printf is atomic.
  530. a244 1
  531.     char buffer[1024];        /* what we actually print */
  532. a245 1
  533.     int i;
  534. a246 1
  535.     SetLock();
  536. d248 1
  537. a248 12
  538.     for (i = 0; i < 25; ++i) {
  539.     buffer[i] = '\b';
  540.     }
  541.     buffer[i] = '\0';
  542.     strcat(buffer, ctime(&now));
  543.     /* 
  544.      * Null out the final newline.
  545.      */
  546.     buffer[strlen(buffer)-1] = '\0';
  547.     printf(buffer);
  548.     fflush(stdout);
  549.     ClearLock();
  550. d300 1
  551. a300 1
  552.     childPid = wait3(0, WNOHANG, 0);
  553. a304 4
  554.     /* no children died (Sprite returns this, when it should return 0) */
  555.     if (childPid < 0 && errno == EWOULDBLOCK) {
  556.         break;
  557.     }
  558. a349 51
  559.  
  560. /*
  561.  *----------------------------------------------------------------------
  562.  *
  563.  * SetLock --
  564.  *
  565.  *    Lock the lock file.
  566.  *
  567.  * Results:
  568.  *    None.
  569.  *
  570.  * Side effects:
  571.  *    None.
  572.  *
  573.  *----------------------------------------------------------------------
  574.  */
  575.  
  576. static void
  577. SetLock()
  578. {
  579.     if (flock(lockFile, LOCK_EX) < 0) {
  580.     perror("flock failed");
  581.     exit(1);
  582.     }
  583. }
  584.  
  585.  
  586. /*
  587.  *----------------------------------------------------------------------
  588.  *
  589.  * ClearLock --
  590.  *
  591.  *    Release the lock file
  592.  *
  593.  * Results:
  594.  *    None.
  595.  *
  596.  * Side effects:
  597.  *    None.
  598.  *
  599.  *----------------------------------------------------------------------
  600.  */
  601.  
  602. static void
  603. ClearLock()
  604. {
  605.     if (flock(lockFile, LOCK_UN|LOCK_EX) < 0) {
  606.     perror("Couldn't release lock file");
  607.     exit(1);
  608.     }
  609. }
  610. @
  611.